Skip to content

Pivoted sparse Cholesky for QuadtoSOCBridge.#2965

Open
samuelsonric wants to merge 1 commit intojump-dev:masterfrom
samuelsonric:master
Open

Pivoted sparse Cholesky for QuadtoSOCBridge.#2965
samuelsonric wants to merge 1 commit intojump-dev:masterfrom
samuelsonric:master

Conversation

@samuelsonric
Copy link

@samuelsonric samuelsonric commented Mar 6, 2026

This PR adds the pivoted sparse Cholesky factorization algorithm in CliqueTrees.jl as a fallback in QuadtoSOCBridge. This algorithm can handle singular matrices, and it is MIT licensed.

Example

julia> using CliqueTrees.Multifrontal, LinearAlgebra, LDLFactorizations

julia> A = [1 1 0; 1 1 0; 0 0 1]
3×3 Matrix{Int64}:
 1  1  0
 1  1  0
 0  0  1

The CliqueTrees factorization correctly reconstructs the matrix.

julia> F = cholesky!(ChordalCholesky(A), RowMaximum());

julia> F.L * F.D * F.L'
3×3 Matrix{Float64}:
 1.0  1.0  0.0
 1.0  1.0  0.0
 0.0  0.0  1.0

The LDLFactorizations factorization does not.

julia> G = ldl(A);

julia> UnitLowerTriangular(G.L) * G.D * UnitLowerTriangular(G.L)'
3×3 SparseArrays.SparseMatrixCSC{Int64, Int64} with 5 stored entries:
 1  1           ⋅
 1  1           ⋅
 ⋅  ⋅  5873643920

Related Pull Requests

@odow
Copy link
Member

odow commented Mar 8, 2026

I need to think about this more. This will conflict if someone loads both CliqueTrees and LDLFactoriztions.

@samuelsonric
Copy link
Author

Ah good point.

@odow
Copy link
Member

odow commented Mar 8, 2026

I'm also not very keen on adding dependencies. I wonder if we can just document this somehow. It's such a small edge-case. Very, very few people will ever need this.

@odow odow mentioned this pull request Mar 8, 2026
6 tasks
@odow
Copy link
Member

odow commented Mar 8, 2026

We haven't released the LDL stuff yet (#2955), so we have a small window to get this right. I'll take a look.

@samuelsonric
Copy link
Author

Also takes BigFloat.

#2959

@odow
Copy link
Member

odow commented Mar 8, 2026

Are there situations when LDLFactorizations is preferable to CliqueTrees?

@samuelsonric
Copy link
Author

Yes: if the matrix is extremely sparse it can be ~2x faster.

@odow
Copy link
Member

odow commented Mar 8, 2026

Is there a better way to check if the factorisation failed other than testing Q = U' * U?

@odow
Copy link
Member

odow commented Mar 8, 2026

For example, your LinearAlgebra.issuccess seems wrong here:

julia> Q = [0 -1; -1 0]
2×2 Matrix{Int64}:
  0  -1
 -1   0

julia> G = LinearAlgebra.cholesky!(
           CliqueTrees.Multifrontal.ChordalCholesky(Q),
           LinearAlgebra.RowMaximum(),
       )
2×2 FChordalCholesky{:L, Float64, Int64} with 3 stored entries:
 0.0    
 0.0  0.0

julia> LinearAlgebra.issuccess(G)
true

julia> U = SparseArrays.sparse(G.U) * G.P
2×2 SparseArrays.SparseMatrixCSC{Float64, Int64} with 3 stored entries:
 0.0  0.0
     0.0

julia> U' * U
2×2 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries:
 0.0  0.0
 0.0  0.0

@samuelsonric
Copy link
Author

LDLFactorizations halts early if it hits a zero pivot, so I think that you can just scan the diagonal.

CliqueTrees (with RowMaximum) does not halt early. However depending on the condition number etc. the factorization can be more or less accurate.

You could try solving Fx = b for some random b and compare Qx to b.

@samuelsonric
Copy link
Author

samuelsonric commented Mar 8, 2026

@odow

We truncate negative pivots to 0 when computing a pivoted factorization. I wasn't thinking about non-PSD matrices. I can change the behavior to something else.

@odow
Copy link
Member

odow commented Mar 8, 2026

So is all(iszero, G.D) sufficient to check for failure? Or I guess you might have some positive values and some negative values projected to zero so you really can tell only by comparing the matrices?

@samuelsonric
Copy link
Author

samuelsonric commented Mar 8, 2026

Currently, you cannot check for failure without solving a problem or reconstructing or something. However, I can push a patch tonight that sets issuccess to false if the algorithm encounters a sufficiently large negative pivot.

Also -- beware. G.D is the identity if you perform a cholesky factorization (cholesky!). It is nontrivial if you perform an LDLt factorization (ldlt!).

@odow
Copy link
Member

odow commented Mar 8, 2026

We just want a method that produces A = B * B' where A is PSD. Robustness is #1 priority. Sparsity is great. Performance is a lesser concern.

@samuelsonric
Copy link
Author

samuelsonric commented Mar 8, 2026

We just want a method that produces A = B * B' where A is PSD. Robustness is #1 priority. Sparsity is great. Performance is a lesser concern.

Right. The current status is this: CliqueTrees is robust for PSD (moreso than LDLFactorizations) but might produce strange results for non-PSD.

Your breaking example (Q = [0 -1; -1 0]) is non-PSD.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants